Repository navigation
Conversation
The atime, mtime, ctime and birthtime getters of Stats and BigIntStats now compute new Date(Math.round(Number(ms))), the same as Node.js. A value with a fraction of 0.5 ms or more rounds up instead of being truncated. A BigInt past 64 bits becomes an Invalid Date instead of a wrapped value. Both classes accept a Number or a BigInt *Ms field. Fixes #42562
|
Updated 7:15 AM PT - Oct 28th, 2026
❌ @robobun, your commit f01089c has 5 failures in
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.325c3488-12d1-4ac7-be80-2298f12df67c
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.b10c0e49-6484-4ce1-ab77-a4523aa3ce84
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.5049b5d0-3fa2-4dae-ba73-4330cf6310d1
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.da69c721-6e00-4e6b-b3e0-1b3283ebbba6
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.5c553973-5f85-4979-824b-c7d047a99cc1
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.0f5e0c72-fb6d-435b-b1f9-0acbd4493935
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.c774c76a-c96a-47f4-a368-62ae5ba08f1c
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.2273ca28-1524-4789-9ec7-65da4afa64cd
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.823e6962-e08d-4369-8596-04562dfc1f28
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.a42ef20b-fcff-42d2-868a-66d369b6d131
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.3c4bfccb-36c0-4a89-9bb2-3693621a2e88
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.1a10b913-21e6-4f79-b989-c0b6d4d91034
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.a256544a-589c-4ead-89d7-0cf70cb23d3e
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.abcf06ab-1270-44f0-bf17-980104046938
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.2c8b91e7-0570-450c-a7a7-3ed27f82f5ff
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.cb3eb6ec-b62d-425d-91a2-8bc8595e11ef
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.ae72316e-4753-448f-81b5-565eb8cfd44e
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.09c829e2-9f74-4e01-9049-f4c422b48d2d
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.80087a79-9956-41d0-90dd-caa3f78ed0dc
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.3c475b1a-9273-4b8e-813f-450961c12f16
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.bb5a0413-4789-45f4-9fb6-759650898837
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.80d6adfe-66e4-4d8a-978c-fe93010f741f
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.decdd986-cc5c-4abd-95a3-7f6870d6cf96
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.b436173f-9f19-4a62-8e0c-68f22bf53031
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.cbc00109-c17b-460f-ae05-b8fed4e990d0
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.b03794c1-1def-4690-b529-adca32ec03d5
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.e4747e1a-d0f0-429a-bab9-b150b564a134
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.d6da6de6-85e4-4b00-955c-cb4f7e42ff93
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.8049114b-4455-49f9-8680-31a295f187b4
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.9a26a55e-473f-4ed4-9d64-2f8ff902b439
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.d4ad77c6-bd08-4ab1-8b65-2438aef5d8f6
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.c6e8e1b7-efab-410c-80be-ffdb52c738d3
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.9c65aa48-5496-420e-819d-7463fec68bf8
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.331e5d16-b7de-46e0-9cd8-6f9fc24f570d
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.80f4fcc4-3bb3-494e-870c-31246175568b
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.7cab3f14-d3aa-43b6-ba23-d61b5027cd90
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.666e92b5-e8e6-4d6a-a175-473e25b4d17d
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.ce05ed23-442b-4911-967c-cc4cf6f1303b
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.c7d56606-fb74-4e9c-af45-ecb342ec40d3
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.cee45cfb-bbd7-46e3-8a18-59de00c2cf19
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.016a77ae-f491-49d0-88f0-ffc118447bb0
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.ef49e052-f19e-4bfc-b7e7-fccb93d5a7e5
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.899a2eec-8adf-435f-b0e2-3139e234051b
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.70c4fe1c-4d89-46df-b666-90bfb26ce7a9
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.e4bfb845-96df-4b02-8434-4d1e3c51f473
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.92ff2590-f31c-40eb-8733-51cd6fa7767d
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.693c25de-f3b1-48cb-b06f-c6d64b848174
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.33455fc2-6243-497f-988a-8fd76b97f830
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.d92a5a00-309b-4cbb-87d4-ab603478b3fd
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.958d672c-0fc7-4efc-bdc1-50c086d4ebe4
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.ae8c6f5a-86eb-45d6-9a16-8b00d1d59716
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.9df83f96-0fc3-4ef6-af51-f2d747a17e40
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.344d51fe-e3a0-499a-8f86-e4da7488172b
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.26611076-7740-4bf5-9ef4-3e372a3557e4
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.7f18c429-710e-4321-8740-dd9bba13cac6
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.c4ee8cab-8e17-4c6f-8e36-57823804fe99
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.e3815e6f-1698-4250-8dec-6d55315250ca
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.e21c258a-9ed7-4fb9-a3eb-314598ba9cf7
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.f28c1e02-69b1-4292-b2b7-2db9c90aeacd
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.12767e2e-44fd-4857-b0e4-560b259208f3
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.fa3fcf3d-d446-4d7b-85f6-50476d309af0
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.bc50ab6c-ce68-4692-9ec4-801669499dc8
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.74519c34-da2e-4701-a21e-066ddb7f68ab
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.1bdd6f10-8681-4405-a4b8-e46aa53da542
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.23f9d0c1-9a35-4e04-b707-cec158eab5ad
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.c3eb5b43-e4ae-4f12-b696-312bd9ff9658
CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.6ff4e978-0dd1-4632-8f33-37c3421831f4🧪 To try this PR locally: bunx bun-pr 42564That installs a local version of the PR into your bun-42564 --bun |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 37 seconds. View limit details
No actionable comments were generated in the recent review. ℹ️ Recent review info
WalkthroughThe change updates ChangesFilesystem statistics date conversion
Priority: Merge Risk:
|
| Check name | Status | Explanation |
|---|---|---|
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Title check | ✅ Passed | The title clearly and concisely describes the primary change: updating Node.js filesystem Stats date-field conversion behavior. |
| Description check | ✅ Passed | The description fully explains the problem, fix, behavior changes, and verification results. It does not use the template headings exactly, but it provides the required information in clearly labeled … |
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
|
The automated review raised no actionable items. No open review threads. CI build #115030 is running. |
|
The second automated review covered 48519f2 (autofix removed an unused import from the test). No actionable items. Waiting on CI build #115030. |
|
The automated review of 08fa3e2 hit its rate limit. That commit only changes the test: it no longer assumes a nanosecond timestamp resolution for mtimeMs (NTFS stores 100 ns). No open review threads. CI build #115031 is running. |
|
The one review nit (an unused writeFileSync import in the test) was already removed in 48519f2. The thread is resolved. Nothing else is open. |
There was a problem hiding this comment.
LGTM — the unused writeFileSync import from the earlier review is gone, and I have nothing further.
What was reviewed:
getDateFieldexception handling:toNumericis followed byRETURN_IF_EXCEPTION;JSBigInt::toNumbercannot throw;asNumber()is safe because ToNumeric guarantees Number-or-BigInt and the BigInt branch converts first.- Semantics vs Node:
Number(x)is spec'd as ToNumeric + BigInt→double (ES2020+), sotoNumeric+JSBigInt::toNumber+jsRoundis exactlynew Date(MathRound(Number(ms))); theisBigInttemplate param is still live for the structure fast-path at line 227. - Real-stat test portability: the
mtimeMsassertion is a range (≥789.5, <790) that holds on ext4/tmpfs/APFS/NTFS, andutimesSyncsets atime explicitly sonoatimemounts don't affect it.
Extended reasoning...
Overview
The PR changes one templated helper, getDateField, in src/jsc/bindings/NodeFSStatBinding.cpp (6 lines) so that fs.Stats/BigIntStats date getters compute new Date(Math.round(Number(ms))) like Node.js does, instead of branching on the class and either wrapping past 64 bits (toBigInt64) or truncating (toNumber → DateInstance::create). It adds a describe block with five tests to test/js/node/fs/fs-stats-constructor.test.ts covering a real stat with a fractional millisecond, the full Math.round input space (±0.5, ±1.5, past-Date-range, Infinity, NaN), BigInts past 2⁶³/2⁶⁴, cross-acceptance of Number/BigInt on either class (including via detached prototype getters), and the Symbol → TypeError path.
Security risks
None. This is a numeric coercion path for filesystem timestamp fields; no auth, crypto, path handling, or untrusted-length arithmetic is involved. The only user-reachable throw is the existing ToNumeric TypeError for Symbol, which is the Node-matching contract.
Level of scrutiny
Low-to-moderate. The C++ change is tiny and mechanical, but it's in a JSC binding where exception-scope discipline matters. I verified: toNumeric is followed by RETURN_IF_EXCEPTION; JSBigInt::toNumber is a pure BigInt→double conversion that cannot throw; after ToNumeric the result is guaranteed Number-or-BigInt by spec, so numeric.asNumber() after the BigInt branch is a validated (not blind) accessor call. I also confirmed against the ES2020+ spec that Number(value) is defined as ToNumeric followed by BigInt→Number, so the PR's toNumeric + JSBigInt::toNumber composition is exactly Number(ms) — including for objects whose valueOf returns a BigInt. jsRound gives Math.round's half-toward-+∞ (so -0.5 → -0, -1.5 → -1), which is what the tests assert and what Node's MathRound does. The isBigInt template parameter is not made dead — it still selects the structure for the fast-path getDirect at line 227.
Other factors
Since the previous review, commit b10313b dropped the unused writeFileSync import I flagged; the current diff imports only Stats, statSync, utimesSync. The tests follow the repo conventions the review rules call out: tempDir from harness, combined-object .toEqual assertions, specific TypeError class on the throw path, and a fresh Stats per input to defeat the getter's own-property cache. The one filesystem-touching test writes its mtimeMs assertion as a range that accounts for the float-precision loss in utimesSync's seconds→nanoseconds conversion (the comment names 789.5999 on Linux and 789.6 on Windows), and only checks mtime/atime — not birthtime, which varies by platform. The remaining four tests overwrite *Ms on a stat of import.meta.path, so they're hermetic and resolution-independent.
src/jsc/bindings/NodeFSStatBinding.cpp: both sides added includes at the same place. Keep both.
|
Build #134190 could not start any build agent (EC2 CapacityLimitExceeded on all six build lanes), so no test ran on the merge commit f01089c. The earlier build #115031 ran the full suite on the same diff: fs-stats-constructor.test.ts passed on every lane, and the only red suites were bun install tests that hit 504s from api.github.com. The diff is ready for review. A maintainer can restart the build when agent capacity is back. |
There was a problem hiding this comment.
LGTM — the earlier nit (unused writeFileSync import) is addressed and the fix is small and self-contained.
What was reviewed:
getDateFieldinsrc/jsc/bindings/NodeFSStatBinding.cpp:toNumericis followed byRETURN_IF_EXCEPTION, and the BigInt-to-Number branch beforeasNumber()mirrors the existingIDLLooseDoubleOrBigIntconverter insrc/jsc/bindings/Bindgen/IDLConvertNumbers.h, soasNumber()never sees a non-Number.- All eight date getters (both
StatsandBigIntStats) route through this one template, so the whole sibling set gets the rounding fix. - Checked
fs-stats-truncate.test.tsand the rest oftest/for assertions on the old truncating behavior — none found.
Extended reasoning...
The PR changes four lines in the shared getDateField template in src/jsc/bindings/NodeFSStatBinding.cpp so fs.Stats and fs.BigIntStats date getters compute new Date(Math.round(Number(ms))) like Node, and adds five tests in test/js/node/fs/fs-stats-constructor.test.ts covering a real utimesSync fixture, a Math.round table including the Date range edge, out-of-range BigInt, cross-class Number/BigInt acceptance, and the Symbol throw. It touches no security-sensitive surface. The coercion sequence is byte-for-byte the pattern already used in IDLConvertNumbers.h, the exception check is present, the only change since my last review is a merge from main plus removal of the import I flagged, and neither file is covered by a CODEOWNER, which decided approve.
|
Closing: #47233 replaces this PR and #42563. It carries the conversion of |
Problem
atime,mtime,ctimeandbirthtimegetters offs.StatsandBigIntStatsconvert*Msto aDatedifferently from Node.js. A realfs.stat()result with a fraction of 0.5 ms or more gives aDate1 ms early. A BigInt at or past 2^63 wraps to 64 bits. A Number*MsonBigIntStats, or a BigInt*MsonStats, throwsTypeError: Conversion from 'BigInt' to 'number' is not allowed.getDateFieldinsrc/jsc/bindings/NodeFSStatBinding.cpp:233. It callstoBigInt64for one class andtoNumberfor the other, with no round.DateInstance::createthen truncates.Fix
getDateFieldnow does what Node'sdateFromMsdoes:new Date(MathRound(Number(ms))). It callstoNumeric, converts a BigInt result withJSBigInt::toNumber, and rounds withjsRound(theMath.roundimplementation, so-0.5gives0and-1.5gives-1).Daterange, so TimeClip gives an Invalid Date. Both classes accept a Number or a BigInt, and each getter works on an object of the other class.test/js/node/fs/fs-stats-constructor.test.ts(4 new tests fail on 1.4.3, pass with the fix). Alsofs.test.ts,fs-stats-truncate.test.ts, and the upstreamtest-fs-stat.js,test-fs-stat-bigint.jsandtest-fs-stat-date.mjs.Background
StatsandBigIntStatsstoreatimeMsand friends as own properties. TheDategetters live on the prototype, compute theDatefrom the*Msfield, and cache it on the instance. Node does the same withObjectDefinePropertyinlib/internal/fs/utils.js.toNumericis the ECMAScript ToNumeric operation. It returns a Number or a BigInt and throws for a Symbol.Number(x)is ToNumeric followed by a BigInt to double conversion, which is whatJSBigInt::toNumberdoes.jsRoundis the function behindMath.roundin JavaScriptCore.std::rounddiffers for negative halves.Notes
Node reference: https://github.com/nodejs/node/blob/v26.3.0/lib/internal/fs/utils.js#L459-L469
The
BigIntStats*Msfields are integer BigInts (the fraction lives in*Ns), so a real BigInt stat is not affected by the round. The test asserts that too.#42518 changes how the getters store the cached
Dateon the instance. It does not touch the conversion, so the two changes do not overlap in behaviour.[human-review] gate passed · iteration 1 · 2 files touched
fails on main (without fix)
passes on PR (with fix)
diff hotspot
gate history · 2 passed · 0 rejected · iteration 1
evidence per changed file
root cause · written by the author bot
The date getters of
fs.StatsandBigIntStatsinNodeFSStatBinding.cppconverted the*Msfield withtoBigInt64for BigInt stats andtoNumberfor Number stats, then handed the result straight to theDateconstructor. That meant the millisecond value was truncated rather than rounded, BigInt values at or beyond 2^63 wrapped to 64 bits instead of producing an Invalid Date, and a*Msvalue of the other numeric type threw a conversion error. The fix uses a single shared coercion for both classes that converts a BigInt to a Number the wayNumber(x)does, appliesMath.round, and…